const { resolve } = require('path')
const cssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
const HtmlWebpackPlugin = require('Html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const workboxWebpackPlugin = require('workbox-webpack-plugin')
const webpack = require('webpack')
process.env.NODE_ENV = 'development';

module.exports = {
  // 1、单入口
  entry: './src/main.js',
  // entry: {
  //  问题：文件过多不宜使用
  //   index: './src/main.js',
  //   text: './src/js/text.js'
  // },
  // 2、出口
  output: {
    // 根据名字进行命名
    filename: 'js/[name].[contenthash:6].js', // ontenthash：根据文件的内容生成相应的hash值，每一个文件的hash都不一样
    path: resolve(__dirname, 'build')
  },
  // 3、loader
  module: {
    rules: [
      // eslint
      /* {
        test: /\.js$/,
        exclude: /node_modules/, // 排除第三方库
        enforce:'pre', // 优先执行
        loader: 'eslint-loader',
        options: {
          // 自动修复eslint错误
          fix: true,
        },
      }, */
      {
        // 以下loader只会匹配一个
        // 注意：不能有两个配置处理同一种类型文件，如果有则将先执行的loader提取出来放在oneOf外面
        oneOf: [
          // css
          {
            test: /\.css$/i,
            use: [
              MiniCssExtractPlugin.loader, // npm i mini-css-extract-plugin -D
              'css-loader',
              // 兼容
              {
                loader: 'postcss-loader',
                options: {
                  postcssOptions: {
                    plugins: [
                      ['postcss-preset-env'],
                    ],
                  },
                },
              },
            ],
          },
          // less
          {
            test: /\.less$/,
            use: [
              MiniCssExtractPlugin.loader,
              'css-loader',
              // 兼容
              {
                loader: 'postcss-loader',
                options: {
                  postcssOptions: {
                    plugins: [
                      ['postcss-preset-env'],
                    ],
                  },
                },
              },
              'less-loader'
            ]
          },
          // img
          {
            test: /\.(gif|pen|jpg|jpge)$/i,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              esModule: false,
              outputPath: 'image'
            }
          },
          // html
          {
            test: /\.html$/,
            loader: 'html-loader'
          },
          // js
          {
            test: /\.m?js$/,
            exclude: /(node_modules|bower_components)/,  // 排除第三方库
            use: [
              {
                //  进程启动大概为600ms，进程通信也有开销
                // 只有工作消耗时间比较长，才需要多进程打包
                loader: 'thread-loader',
                options: {
                  workers: 2 // 进程两个
                }
              },
              // 只要是将loader放在thread-loader的后面就会进行多进程打包
              {
                loader: 'babel-loader',
                options: {
                  presets: ['@babel/preset-env'], // 预设：告诉babel怎么样做兼容性处理
                  plugins: ['@babel/plugin-proposal-object-rest-spread'],
                  // 开启babel缓存
                  // 第二次构建时,会读取之前的缓存,从而提高性能
                  cacheDirectory: true // 第二次打包更快
                },
              }
            ]
          },
          // media
          {
            exclude: /\.(html|css|js|less)$/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]',
              // outputPath: 'media'
            }
          }
          // to do...
        ]
      }
    ]
  },
  // 4、插件
  plugins: [
    // css压缩
    new cssMinimizerWebpackPlugin(),
    // html 打包压缩
    new HtmlWebpackPlugin({
      template: './src/public/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    }),
    // 提取css
    new MiniCssExtractPlugin({
      filename: 'css/index.[contenthash:6].css'
    }),
    // PWA：渐进式网络开发应用程序（离线可以访问）
    new workboxWebpackPlugin.GenerateSW({
      // 1.帮助 serverceworker 快速启动
      // 2.删除旧的 serverceworker
      clientsClaim: true,
      skipWaiting: true
    }),
    // 告诉webpack哪些库不用打包，同时使用的名称也得变
    new webpack.DllReferencePlugin({
      manifest: resolve(__dirname, 'dll/manifest.json')
    })
  ],
  // 作用：
  // 1、可以将node_module中的依赖包单独打一个chunk最终输出
  // 2、多个地方使用同一个依赖包，则只打包一次
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  },
  // 5、环境
  mode: 'production',
  // 6、有些文件通过cdn引入的第三方包不需要打包
  //   注意:如果忽略了打包文件，则需要手动引入该文件
  externals: {
    // 忽略库名 -- npm包名 例如：
    jquery: 'jQuery' // 
  }
}

